/*
    Copyright (c) 2009 Pavol Malosek a.k.a. malo

    This file is part of ComComLib.

    ComComLib is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.

    ComComLib is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef __DLPARSER_HPP_INCLUDED__
#define __DLPARSER_HPP_INCLUDED__

#include <lcc/device.hpp>

namespace lcc
{

    enum parser_state_t {
        state_unknown,
        state_record_header,
        state_adc_byte_hi,
        state_adc_byte_lo
    };

#pragma pack(push)
#pragma pack(1)
    struct record_header_t {
        uint8_t seconds;
        uint8_t minutes;
        uint8_t hours;
        uint8_t day;
        uint8_t months;
        uint8_t years;
        uint8_t per_l;
        uint8_t per_h;
        uint8_t kanaly;
    };
#pragma pack(pop)

    class parser_t
    {
        public:
            parser_t (device_info_t *device_info_);

            //  Parse buffer, return number of recordes produced.
            int parse (const unsigned char *buff_, size_t size_);

            //  Add records witch parser could produce to device.
            //  Returns number of new records produced.
            unsigned int flush_records (device_t *device_);
        private:
            //  Device info structure
            device_info_t *device_info;            

            //  State of the parser.
            parser_state_t state;
            
            //  Count of subsequent 0xff bytes.
            unsigned int count_0xff;

            //  Current writting position in record_header.
            uint8_t *header_pos;

            //  Record header buffer.
            record_header_t record_header;

            //  Current logger logging period - taken from last record header.
            unsigned int cur_per;

            //  Currnet number of active channels - taken from last header.
            unsigned int cur_act_channels_count;

            //  Current record timestamp in seconds.
            uint64_t cur_stamp;

            //  ADC value
            uint16_t adc_value;

            //  List with prodiced records.
            std::list<record_t> records;

            //  Current record
            record_t cur_record;

            //  Current adc parsing memory position.
            //  0 for first adc value, 1 for second adc value ...
            unsigned int adc_mem_pos;

            //  Value index in record_t's values array. Is calculated from 
            //  act_channels_count and act_channels mask.
            //  For example if mask is 0x03 (2 channles active) function 
            //  returns 0 for mem_order_ 0 and 1 for mem_order_ 1.
            //  For mask 0x02 (1 channel (1st) active) function returns 1 for 
            //  mem_order_ 0.
            unsigned int value_idx (unsigned int mem_order_);

            const char *parser_state_to_string (parser_state_t state_);

            //  Converts BCD values from BCD to int.
            void convert_record_header_values (void);
    };
}
#endif

